#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <sys/stat.h>
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */
#include <dirent.h>
#include "SFtpHdr.h"

#define MAXPENDING 5
#define BUF_SIZE 1024

char *buf = 0;
unsigned int buf_len = 0;


int recvString(int, char *, unsigned int);
int sendString(int, const char *);

int filter(const struct dirent *dirent) {
    if (buf_len < buf_len + strlen(dirent->d_name) + 5) {
        char *temp = buf;
        buf = (char *)malloc(buf_len * 2 + 1);
        memset(buf, 0, buf_len * 2 + 1);
        memcpy(buf, temp, buf_len);
        buf_len *= 2;
        free(temp);
    }
    strcat(buf, dirent->d_name);
    strcat(buf, "     ");
}

void rcd(int sock) {
    char input[256];

    recvString(sock, input, 256);
    chdir(input);
}

void rls(int sock) {
    struct dirent **filelist;

    buf_len = 1024;
    buf = (char *)malloc(buf_len + 1);
    memset(buf, 0, buf_len);
    scandir(".", &filelist, filter, alphasort);
    sendLongString(sock, buf);

    free(buf);
}

int recvMsg(int clntSock) {
    char msgType[256], filename[256];
    
    recvString(clntSock, msgType, sizeof(msgType));
    printf("msgType : %s\n", msgType);
    if (!strcmp(msgType, FileUpReq)) {
        printf("FileUpload Start\n");

        recvFile(clntSock, 0);

        printf("FileUpload End\n");
    } else if(!strcmp(msgType, FileDownReq)) {
        printf("FileDownload Start\n");
        recvString(clntSock, filename, sizeof(filename));
        sendFile(clntSock, filename, 0);
        printf("FileDownload End\n");
    } else if(!strcmp(msgType, Rls)) {
        printf("Rls Start\n");
        rls(clntSock);
        printf("Rls End\n");
    } else if(!strcmp(msgType, Rcd)) {
        rcd(clntSock);
    } else if(!strcmp(msgType, LogOut)) {
        return 0;
    }
    return 1;
}

int main(int argc, char *argv[]) {
    int servSock;                    /* Socket descriptor for server */
    int clntSock;                    /* Socket descriptor for client */
    struct sockaddr_in servAddr; /* Local address */
    struct sockaddr_in clntAddr; /* Client address */
    unsigned short servPort;     /* Server port */
    unsigned int clntLen;            /* Length of client address data structure */
    
    if (argc != 2) {   /* Test for correct number of arguments */
        fprintf(stderr, "Usage:  %s <Server Port>\n", argv[0]);
        exit(1);
    }
    
    servPort = atoi(argv[1]);  /* First arg:  local port */

    if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        fprintf(stderr, "socket() failed");
    
    /* Construct local address structure */
    memset(&servAddr, 0, sizeof(servAddr));   /* Zero out structure */
    servAddr.sin_family = AF_INET;                /* Internet address family */
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    servAddr.sin_port = htons(servPort);      /* Local port */
    
    /* Bind to the local address */
    if (bind(servSock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
        fprintf(stderr, "bind() failed");
    
    /* Mark the socket so it will listen for incoming connections */
    if (listen(servSock, MAXPENDING) < 0)
        fprintf(stderr, "listen() failed");
    
    /* Set the size of the in-out parameter */
    clntLen = sizeof(clntAddr);
    
    while(1) {
        /* Wait for a client to connect */
        if ((clntSock = accept(servSock, (struct sockaddr *) &clntAddr,
                               &clntLen)) < 0)
            fprintf(stderr, "accept() failed");
        
        /* clntSock is connected to a client! */
        
        while(recvMsg(clntSock) > 0);
    }
    
    printf("Quit!!\n");

}
